perm filename OBJCR.TEX[CLS,LSP] blob sn#847177 filedate 1987-10-15 generic text, type C, neo UTF8
COMMENT āŠ—   VALID 00009 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00003 00002	Page 1-5   Creating Instances of Classes
C00006 00003	Page 1-27:  New Chapter:  Object Creation and Initialization 
C00013 00004	\beginsubSection{Initialization Arguments}
C00018 00005	\beginsubSection{Declaring the Validity of Initialization Arguments}
C00021 00006	\beginsubsection{Defaulting of Initialization Arguments}
C00027 00007	\beginsubSection{Rules for Duplication of Initialization Arguments}
C00032 00008	\beginsubSection{Methods for Initialize-instance}
C00037 00009	\beginsubSection{Procedural Definition of Make-instance}
C00055 ENDMK
CāŠ—;
Page 1-5   Creating Instances of Classes

[Replace existing text with this.   The goal is to give an overview of
creating instances.   It's too early to discuss initialization in detail
because we haven't discussed methods yet.]

The generic function {\bf make-instance} creates and returns a new
instance of a class.  The \OS\ provides a flexible means for specifying
how a new instance is to be initialized.  For example, it is possible to
specify the initial values for slots in newly-created instances, either by
giving an argument to {\bf make-instance} or by providing a default
initial value.  Further initialization activities can be performed by
methods written for generic functions that are part of the initialization
protocol.  The complete initialization protocol is described in the
section ``Object Creation and Initialization.''

Page 1-27:  New Chapter:  Object Creation and Initialization 

\beginSection{Object Creation and Initialization}

The generic function {\bf make-instance} creates and returns a new
instance of a class.  The first argument is a class or the name of a
class, and the remaining arguments are an {\bit initialization argument}
list.  

Initialization consists of several distinct steps, including:  combining
the explicitly supplied initialization arguments with default values for
the unsupplied initialization arguments, checking the validity of the
initialization arguments, allocating storage for the instance, filling
slots with values, and executing user-supplied methods that perform
additional initialization.  The \OS\ defines {\bf make-instance} in a
procedural way: each step is represented by a generic function.  This
provides a mechanism for customizing each step.  In addition, {\bf
make-instance} is a generic function and can be customized.

The \OS\ specifies default methods for each step, so there is well-defined
standard behavior for the entire initialization procedure.  The standard
behavior provides four simple mechanisms for controlling
initialization:

\beginlist

\item{\bull} Declaring a symbol to be an initialization argument for a
slot, by using the {\bf :initarg} slot option. This allows one to
provide a value for a slot in a call to {\bf make-instance}.

\item{\bull} Supplying a default value form for an initialization
argument, by using the {\bf :default-initargs} class option.  This default
value is used if the initialization argument is not explicitly provided as
an argument to {\bf make-instance}.

\item{\bull} Supplying a default value form for a slot, by using the {\bf
:initform} slot option.  This default value is stored in the slot if no
initialization argument associated with that slot is given as an argument
to {\bf make-instance} or defaulted by {\bf :default-initargs}.

\item{\bull} Defining methods for {\bf initialize-instance}.  The
slot-filling behavior described above is implemented by a system-supplied
default method for {\bf initialize-instance}.  Additional control over
initialization can be obtained by writing methods for {\bf
initialize-instance}.  In most cases {\bf :after} methods are appropriate
for this purpose, because they are called after the default method that
fills the slots and thus do not override the normal slot-filling behavior.

\endlist

Note that the object creation and initialization procedure can be
controlled at two different levels.  The standard behavior offers the four
mechanisms mentioned above; this level can be considered the Programmer
Interface level.  At the meta-object level, greater control can be exerted
over each step of this procedure; this level can be considered the
interface for experimentation with alternative object-oriented paradigms.

There is one general guideline that helps distinguish between the
Programmer Interface and the Meta-object levels of programming.  To
customize behavior at the Programmer Interface level, methods that
specialize on instances are written.  That is, the arguments that select
methods are instances.  To customize behavior at the Meta-object level,
methods that specialize on classes are written.  That is, the arguments
that select methods are classes.

\beginsubSection{Initialization Arguments}

An initialization argument can be used to control
object creation and initialization.  The {\bf \&key} arguments to {\bf
make-instance} are initialization arguments.  It is often convenient to
use keyword symbols to name initialization arguments, but the name of an
initialization argument can be any symbol, including {\bf nil}.  There are
two purposes for an initialization argument:  to fill a slot with a value
or to provide an argument for an initialization method.  A single
initialization argument can be used for more than one purpose.

An {\bit initialization argument list} is a list of alternating
initialization argument names and values.  Its structure is identical to a
property list and also identical to the portion of an argument list
processed for {\bf \&key} parameters.  As in those lists, if an
initialization argument name appears more than once in an initialization
argument list, the leftmost occurrence supplies the value and the
remaining occurrences are ignored.  The arguments to {\bf make-instance}
(after the first argument) are an initialization argument list.  As in an
{\bf \&key} argument list, {\bf :allow-other-keys} can appear in an
initialization argument list, and if its value is non-{\bf nil},
error-checking of initialization argument names is disabled.

An initialization argument can be associated with a slot.  If
the initialization argument has a value in the initialization argument
list, the value is stored into the slot of the newly-created object,
overriding any initform associated with the slot.  A single initialization
argument can fill more than one slot.  An initialization argument that
fills a shared slot stores its value into the shared slot, replacing any
previous value.

An initialization argument can be associated with a method.
Such an initialization argument is intended as an argument for one or more
methods for {\bf initialize-instance} or {\bf allocate-instance}.  When an
object is created, the method is called with the initialization argument's
name and value as a keyword argument, and the method uses the value however
it chooses.  If the initialization argument has no value in the
initialization argument list, the method's lambda-list supplies a default
value.

\endsubSection%{Initialization Arguments}
\beginsubSection{Declaring the Validity of Initialization Arguments}

The generic function {\bf make-instance} checks the validity of the
initialization arguments and signals an error if an initialization
argument is supplied that is not valid.  An initialization argument is
declared as valid in the same place where its purpose (whether to fill a
slot or to supply an argument to a method) is stated.

Initialization arguments that fill slots are declared as valid by the {\bf
:initarg} slot option to {\bf defclass}.  The {\bf :initarg} slot option
is inherited from superclasses.  Thus, the set of valid initialization
arguments that fill slots for a class is the union of the initialization
arguments declared by the class and its superclasses.

Initialization arguments that supply arguments to methods are declared as
valid by defining methods for {\bf initialize-instance} or {\bf
allocate-instance}.  The keyword name of each keyword parameter specifier
in the method's lambda-list becomes an initialization argument for all
classes for which this method is applicable.  Thus, method inheritance
controls the set of valid initialization arguments that supply arguments
to methods.

The set of valid initialization arguments for a class is the set of valid
initialization arguments that either fill slots or supply arguments to
methods along with the pre-defined initialization argument {\bf
:allow-other-keys}.  The default for {\bf :allow-other-keys} is {\bf nil},
and its specification is the same as Common Lisp defines for {\bf \&key}
argument lists.

\endsubSection%{Declaring the Validity of Initialization Arguments}
\beginsubsection{Defaulting of Initialization Arguments}

A {\bit default value form} can be supplied for an initialization
argument.  The way to provide a default value form for an initialization
argument is to use the {\bf :default-initargs} class option.  A default
value form is usually specified by a different class from the class that
declared the initialization argument as valid.  Thus, {\bf
:default-initargs} is usually used to supply a default value for an
inherited initialization argument.

The {\bf :default-initargs} class option is inherited.   See ``Inheritance of 
Class Options.''

The {\bf :default-initargs} class option is a list of alternating
initialization argument names and forms.  Each form is the default value
form for the corresponding initialization argument.  The default value
form of an initialization argument is used only if that initialization
argument does not appear in the arguments to {\bf make-instance}.  In that
case, the default value form is evaluated in the lexical environment of
the {\bf defclass} form that supplied it, and the resulting value is used
as the initialization argument's value.  

The initialization arguments supplied to {\bf make-instance} are combined
with unsupplied defaulted initialization arguments to a produce a {\bit
defaulted initialization argument list}. A defaulted initialization
argument list is a list of alternating initialization argument names and
values in which unsupplied initialization arguments are defaulted and in
which the explicitly supplied initialization arguments appear earlier in
the list than the defaulted initialization arguments.  Defaulted
initialization arguments are ordered according to the order in the class
precedence list of the classes that supplied the default values.

The {\bf :default-initargs} option is used only to provide default values
for initialization arguments; it does not declare a symbol as a valid
initialization argument name.

There is a distinction between the purposes of {\bf :default-initargs} and
{\bf :initform}, with respect to initialization arguments that fill slots.
The {\bf :default-initargs} class option allows the user to give a default
value form for an initialization argument without knowing whether or not
the initialization argument fills a slot.  If that initialization argument
is not explicitly supplied in a call to {\bf make-instance}, the default
value form is used, just as if it had been supplied in the call.  In
contrast, the {\bf :initform} slot option allows the user to give a
default initial value form for a slot.  An {\bf :initform} form is used
only if no initialization argument associated with that slot is given as
an argument to {\bf make-instance} or defaulted by {\bf
:default-initargs}.  

The \OS\ does not guarantee any given order of evaluation of default value
and {\bf :initform} forms.  If the order of evaluation is important, {\bf
initialize-instance} methods should be used instead.  In most programs,
the {\bf :initform} and default value forms are either constants or
side-effect-free forms that construct new objects; forms with side-effects
are permitted, but are not recommended.

\endsubsection%{Defaulting of Initialization Arguments}
\beginsubSection{Rules for Duplication of Initialization Arguments}

The following rules specify what happens when initialization arguments are
duplicated.

\beginlist

\item{\bull} The {\bf :initarg} slot option may be specified more than
once for a given slot.

\item{\bull} It is valid for a single initialization argument to
initialize more than one slot if the same initialization argument name
appears in more than one {\bf :initarg} slot option.

\item{\bull} It is valid for a single initialization argument to appear 
in more than one initialization method lambda-list.

\item{\bull} It is valid for a given initialization argument name to
appear both in an {\bf :initarg} slot option and in the lambda-list
of an initialization method.

\item{\bull} If two initialization arguments that initialize the same slot
are given in the arguments to {\bf make-instance}, the leftmost of these
initialization arguments in the initialization argument list prevails,
even if the two initialization arguments have different names.  This
behavior is consistent with the behavior of property lists and with the
portion of an argument list processed for {\bf \&key} parameters.

\item{\bull} If two different initialization arguments that initialize the
same slot have default values, and neither is given explicitly in the
arguments to {\bf make-instance}, the initialization argument that appears
in a {\bf :default-initargs} class option in the more specific of the two
classes prevails. If they appear in the same class, the one whose mention
is leftmost in the {\bf defclass} form prevails.  During the defaulting of
initialization arguments, the defaults are appended to the end of the
initialization argument list in this order.

\item{\bull} If there are two different initialization arguments that
initialize the same slot, and one was given explicitly in the arguments to
{\bf make-instance} while the other was defaulted using {\bf
:default-initargs}, the explicit one prevails.  This follows from the
previous two rules.

\item{\bull} If a slot has both an {\bf :initform} and an {\bf :initarg}
slot option, and the initialization argument is defaulted using {\bf
:default-initargs}, then the {\bf :initform} form is neither used nor
evaluated.

\endlist

The following is an example of the above rules:

\screen!

  (defclass a () ((x :initarg a)))
  (defclass b (a) ((x :initarg b))
    (:default-initargs a 1 b 2))

                                 DEFAULTED 
  FORM                 INITIALIZATAION ARGUMENT LIST    CONTENTS OF X SLOT
  (make-instance 'b)             (a 1 b 2)                       1
  (make-instance 'b 'a 3)        (a 3 b 2)                       3
  (make-instance 'b 'b 4)        (b 4 a 1)                       4
  (make-instance 'b 'a 1 'a 2)   (a 1 a 2 b 2)                   1

\endscreen!

\endsubSection%{Rules for Duplication of initialization arguments}
\beginsubSection{Methods for Initialize-instance}

The generic function {\bf initialize-instance} uses standard method
combination.  Methods for {\bf initialize-instance} can be defined in
order to perform any initialization that cannot be achieved with the
simple slot-filling mechanisms.

During initialization, {\bf initialize-instance} is invoked
after the following actions have been taken:

\beginlist 

\item{\bull} The defaulted initialization argument list is computed by
combining the supplied initialization argument list with any default
initialization arguments for the class.

\item{\bull} The validity of the defaulted initialization argument list is
checked.  If any of the initialization arguments has not been declared as
valid, an error is signaled.

\item{\bull} A new instance whose slots are uninitialized is created.

\endlist

The generic function {\bf initialize-instance} is then called with the
new instance and the defaulted initialization argument list.  The
system-supplied default method is a primary method that initializes the
slots with values according to the initialization argument list.  This
default method behaves as follows on each slot, whether shared or local:

\beginlist

\item{\bull} If an initialization argument in the defaulted initialization
argument list specifies a value for that slot, that value is stored into
the slot.  (This is true even if a {\bf :before} method has stored a value
in the slot.)

\item{\bull} Otherwise, if the slot is uninitialized and has an {\bf
:initform} form, that form is evaluated and the result is stored into the
slot.

\item{\bull} The duplicate-resolution rules mentioned in the section
``Rules for Duplication of Initialization Arguments'' are obeyed.

\endlist

User-defined {\bf :after} methods are a good way to customize 
this step of the initialization process because they will be run
after the default activities of {\bf initialize-instance}.
Care should be taken to not supply primary methods
that override the default primary method unless the default activities
of {\bf initialize-instance} are not desired.

The \OS\ provides two functions that are useful in the bodies of {\bf
initialize-instance} methods.  The function {\bf slot-boundp} returns a
boolean value that states whether the slot has a value; this enables
writing {\bf :after} methods for {\bf initialize-instance} that initialize
slots only if they have not already been initialized.  The function {\bf
slot-makunbound} restores a slot to the uninitialized state.

Implementations are permitted to make certain optimizations of {\bf
initialize-instance}.  The description of {\bf initialize-instance} in
Chapter~2 mentions the possible optimizations.  One possible optimization
has the following impact on user-supplied methods:  {\bf :before} and {\bf
:around} methods for {\bf initialize-instance} cannot rely on all the
slots being uninitialized.

\endsubSection%{Methods for INITIALIZE-INSTANCE }
\beginsubSection{Procedural Definition of Make-instance}

The generic function {\bf make-instance} behaves as if it were defined as
follows, except that certain optimizations are permitted:

\screen!

(defmethod make-instance ((class standard-class) &rest initargs)
  (setq initargs (default-initargs class initargs))
  (check-initargs class initargs)  
  (let ((instance (apply #'allocate-instance class initargs)))
    (apply #'initialize-instance instance initargs)
    instance))

(defmethod make-instance ((class-name symbol) &rest initargs)
  (apply #'make-instance (symbol-class class-name) initargs))

\endscreen!

This procedure can be customized at either the Programmer Interface level,
the Meta-object level, or both.  

Customizing at the Programmer Interface level includes using the {\bf
:initform}, {\bf :initarg}, and {\bf :default-initargs} options to {\bf
defclass}, as well as defining methods for {\bf initialize-instance}.  The
Meta-object level supports extra customization by defining methods for:
{\bf make-instance}, {\bf default-initargs}, {\bf check-initargs}, and
{\bf allocate-instance}.  Chapter~3 documents each of these generic
functions and the system-supplied default methods.

As noted above, certain optimizations of the {\bf make-instance} procedure are
permitted.  The description of {\bf initialize-instance} in Chapter~2 mentions
some possible optimizations to this procedure.   Additional
optimizations are possible, including inlining and constant-folding of
method lookup and method bodies, provided that the programming
environment either prohibits redefining these methods or updates
everything when they are redefined.  

Because of optimization, methods for the meta-object generic functions
listed may not actually be called on every call to {\bf make-instance} or may
not receive exactly the arguments that would be expected.  For example,
{\bf check-initargs} might actually be called before {\bf default-initargs} rather
than after, if it has already been determined that the default initialization arguments
will pass {\bf check-initargs}.

\endsubSection%{Procedural Definition of MAKE-INSTANCE}